/**
 * Copyright (c) 2018, wuyy All rights reserved.
 * wuyy 专有/保密源代码,未经许可禁止任何人通过任何渠道使用、修改源代码.
 * QQ:16349023
 * 项目名称 : com.wy2.eclipse.tool.ui
 * @version V1.0
 */
package com.wy2.eclipse.tool.ui.dialog;

import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.internal.text.revisions.Colors;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import com.wy2.core.PropertiesDocument;
import com.wy2.core.database.DatabaseType;
import com.wy2.core.database.DbConnectStringBuilder;
import com.wy2.core.date.DateTime;
import com.wy2.core.tool.StringTools;
import com.wy2.eclipse.tool.lib.common.IDEUtils;
import com.wy2.eclipse.tool.ui.resource.Messages;
import com.wy2.generator.config.DatabaseConsts;
import com.wy2.generator.config.GeneratorConsts;
import com.wy2.generator.database.JdbcConnectionConfiguration;
import com.wy2.generator.database.JdbcConnectionFactory;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;

/**
 * 数据库配置对话窗
 * @author wuyy<16349023@qq.com>
 * @date 2018年1月19日下午3:20:51
 * 
 */
public class DatabaseConfigDialog extends Dialog {
    private static final Logger logger=LoggerFactory.getLogger(DatabaseConfigDialog.class);
    
    private final IProject project;
    private final File configFile;
    private TextViewer textViewer;
    Combo comboDbType;
    private Text textDbHost;
    private Text textDbPort;
    private Text textDbInstance;
    private Text textDbUser;
    private Text textDbPassword;
    private Text textOtherConnectionInfo;
    private Text textDbDriver;

//    /**
//     * Create the dialog.
//     * @param parentShell
//     */
//    public DatabaseConfigDialog(Shell parentShell) {
//        super(parentShell);
//    }
    
    public DatabaseConfigDialog(Shell parentShell,IProject project,File configFile) {
        super(parentShell);
        this.project=project;
        this.configFile=configFile;
    }
    
    
    /** 
     * @param newShell 
     * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
     */
    @Override
    protected void configureShell(Shell newShell) {
        newShell.setText(Messages.getString("wy2.dialog.DatabaseConfigDialog.title"));
        super.configureShell(newShell);
    }

    /**
     * Create contents of the dialog.
     * @param parent
     */
    @Override
    protected Control createDialogArea(Composite parent) {
        Composite container = (Composite) super.createDialogArea(parent);
        container.setLayout(new FillLayout(SWT.HORIZONTAL));
        
        SashForm sashForm = new SashForm(container, SWT.VERTICAL);
        
        Group group = new Group(sashForm, SWT.NONE);
        group.setText("配置");
        FillLayout fillLayout = new FillLayout(SWT.HORIZONTAL);
        fillLayout.marginHeight=10;
        fillLayout.marginWidth=10;
        fillLayout.spacing=10;
        group.setLayout(fillLayout);

        
        Composite compositeInput = new Composite(group, SWT.NONE);
        GridLayout gridLayout = new GridLayout(4, true);
        gridLayout.verticalSpacing=10;
        gridLayout.horizontalSpacing=10;
        gridLayout.marginHeight=5;
        gridLayout.marginWidth=5;
        compositeInput.setLayout(gridLayout);
        
        Label lblNewLabel = new Label(compositeInput, SWT.NONE);
        lblNewLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
        lblNewLabel.setText("数据源类型");
        
        comboDbType = new Combo(compositeInput, SWT.READ_ONLY);
        comboDbType.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
        comboDbType.addSelectionListener(new SelectionAdapter(){
            @Override
            public void widgetSelected(SelectionEvent e) {
                String dbName = comboDbType.getText();
                DatabaseConfigDialog.this.onChangeDbtype(dbName);
            }
        });
        
        Label lblNewLabel_7 = new Label(compositeInput, SWT.NONE);
        lblNewLabel_7.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
        lblNewLabel_7.setText("数据库驱动");
        
        textDbDriver = new Text(compositeInput, SWT.BORDER);
        textDbDriver.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
        
        Label lblNewLabel_1 = new Label(compositeInput, SWT.NONE);
        lblNewLabel_1.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
        lblNewLabel_1.setText("数据库主机");
        
        textDbHost = new Text(compositeInput, SWT.BORDER);
        textDbHost.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
        
        Label lblNewLabel_2 = new Label(compositeInput, SWT.NONE);
        lblNewLabel_2.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
        lblNewLabel_2.setText("数据库端口");
        
        textDbPort = new Text(compositeInput, SWT.BORDER);
        textDbPort.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
        
        Label lblNewLabel_3 = new Label(compositeInput, SWT.NONE);
        lblNewLabel_3.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
        lblNewLabel_3.setText("数据库实例");
        
        textDbInstance = new Text(compositeInput, SWT.BORDER);
        textDbInstance.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
        
        Label lblNewLabel_4 = new Label(compositeInput, SWT.NONE);
        lblNewLabel_4.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
        lblNewLabel_4.setText("用户名");
        
        textDbUser = new Text(compositeInput, SWT.BORDER);
        textDbUser.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
        
        Label lblNewLabel_5 = new Label(compositeInput, SWT.NONE);
        lblNewLabel_5.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
        lblNewLabel_5.setText("密码");
        
        textDbPassword = new Text(compositeInput, SWT.BORDER);
        textDbPassword.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
        
        Label lblNewLabel_6 = new Label(compositeInput, SWT.NONE);
        lblNewLabel_6.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
        lblNewLabel_6.setText("其它连接信息");
        
        textOtherConnectionInfo = new Text(compositeInput, SWT.BORDER);
        textOtherConnectionInfo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
        
        

        
        
        
        
        //提示信息
        Group groupTip = new Group(sashForm, SWT.NONE);
        groupTip.setLayout(new FillLayout(SWT.HORIZONTAL));
        groupTip.setText("提示信息");
        
        textViewer = new TextViewer(groupTip, SWT.BORDER | SWT.READ_ONLY | SWT.WRAP);
        StyledText styledText = textViewer.getTextWidget();
        styledText.setText("请根据实际情况输入正确信息!");
        sashForm.setWeights(new int[] {3,1});
        
        initData();
        

        return container;
    }
    
    /**
     * 初始化数据
     */
    protected void initData() {
        
        for (DatabaseType databaseType : DatabaseType.values()) {
            comboDbType.add(databaseType.getDbName());
        }
        comboDbType.select(0);
        if(configFile!=null) {
            PropertiesDocument propDoc=new PropertiesDocument(true);
            try {
                propDoc.loadAndMerge(null, true, configFile.getAbsolutePath());
                
                textDbDriver.setText(propDoc.getProperty(DatabaseConsts.CONFIG_CONNECT_DRIVER_CLASS));
                textDbUser.setText(propDoc.getProperty(DatabaseConsts.CONFIG_CONNECT_USER_ID));
                textDbPassword.setText(propDoc.getProperty(DatabaseConsts.CONFIG_CONNECT_PASSWORD));
                DbConnectStringBuilder dbConnectStringBuilder = DbConnectStringBuilder.parse(propDoc.getProperty(DatabaseConsts.CONFIG_CONNECT_CONNECTION_URL));
                comboDbType.setText(dbConnectStringBuilder.getDatabaseType().getDbName());
                textDbHost.setText(dbConnectStringBuilder.getHost());
                textDbInstance.setText(dbConnectStringBuilder.getDbName());
                textDbPort.setText(dbConnectStringBuilder.getPort().toString());
                textOtherConnectionInfo.setText(dbConnectStringBuilder.getOtherString());
            } catch (IOException e) {
                logger.warn("加载配置异常", e);
            }
        }
    }
    
    protected void onChangeDbtype(String dbName) {
        DatabaseType dbType=DatabaseType.parse(dbName);
        textDbPort.setText(dbType.getDefaultPort().toString());
        textDbDriver.setText(dbType.getDefaultDriver());
        textOtherConnectionInfo.setText(dbType.getOtherConnectInfo());
    }
    

    /**
     * Create contents of the button bar.
     * @param parent
     */
    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        createButton(parent, IDialogConstants.ABORT_ID, "测试连接", true);
        createButton(parent, IDialogConstants.OK_ID, "保存", true);
        createButton(parent, IDialogConstants.CANCEL_ID, "关闭", false);
    }
    
    @Override
    protected void buttonPressed(int buttonId) {
        if (buttonId == IDialogConstants.OK_ID) {
            saveConfig();            
        }else if(buttonId==IDialogConstants.CANCEL_ID) {
            this.setReturnCode(Window.CANCEL);
            this.close();
        }else if(buttonId==IDialogConstants.ABORT_ID) {
            testConnect();
        }
        super.buttonPressed(buttonId);
    }
    
    private void saveConfig() {
        Button btn = this.getButton(IDialogConstants.OK_ID);
        btn.setVisible(false);
        final List<String> errors=new ArrayList<>();
        PropertiesDocument jdbcConfigDoc = getJdbcConfiguration(errors,true);
        if(errors.size()>0) {
            StringBuilder errorSb=new StringBuilder();
            for (String errorStr : errors) {
                errorSb.append(errorStr+"\n");
            }
            textViewer.getTextWidget().setText(errorSb.toString());
            textViewer.getTextWidget().setForeground(new Color(null, 255, 0, 0));
        }else {
            try {
                jdbcConfigDoc.saveToXml(configFile.getAbsolutePath(), "修改于: "+DateTime.Now().toString());
                //textViewer.getTextWidget().setText("保存数据库配置信息成功");
                //textViewer.getTextWidget().setForeground(new Color(null, 0, 0, 0));
                logger.info("保存数据库配置信息成功");
                IDEUtils.refreshProject(project);
                this.setReturnCode(Window.OK);
                this.close();
            } catch (IOException e) {
                logger.error("保存数据库配置信息异常", e);
                textViewer.getTextWidget().setText("保存数据库配置信息异常");
                textViewer.getTextWidget().setForeground(new Color(null, 255, 0, 0));
            }
        }
        
        btn.setVisible(true);
    }
    
    private void testConnect() {
        Button btn = this.getButton(IDialogConstants.ABORT_ID);
        btn.setVisible(false);
        
        final List<String> errors=new ArrayList<>();
        PropertiesDocument jdbcConfigDoc = getJdbcConfiguration(errors,false);
        
        
        if(errors.size()>0) {
            StringBuilder errorSb=new StringBuilder();
            for (String errorStr : errors) {
                errorSb.append(errorStr+"\n");
            }
            textViewer.getTextWidget().setText(errorSb.toString());
            textViewer.getTextWidget().setForeground(new Color(null, 255, 0, 0));
        }else {
            textViewer.getTextWidget().setText("正在尝试连接数据库...");
            textViewer.getTextWidget().setForeground(new Color(null, 0, 0, 0));
            
            
            JdbcConnectionConfiguration jdbcConnectionConfig=new JdbcConnectionConfiguration();
            jdbcConnectionConfig.load(jdbcConfigDoc);

            
            logger.info("连接信息：{}", jdbcConnectionConfig);
            
            JdbcConnectionFactory jdbcConnectionFactory=new JdbcConnectionFactory(jdbcConnectionConfig);
            try {
                Connection conn = jdbcConnectionFactory.getConnection();
                if(conn==null) {
                    textViewer.getTextWidget().setText("数据库连接失败");
                    textViewer.getTextWidget().setForeground(new Color(null, 255, 0, 0));
                }else {
                    DatabaseMetaData dbMetaData = conn.getMetaData();
                    logger.info("数据库连接成功,数据库: {} {}", dbMetaData.getDatabaseProductName(),dbMetaData.getDatabaseProductVersion());
                    conn.close();
                    textViewer.getTextWidget().setText("数据库连接成功");
                    textViewer.getTextWidget().setForeground(new Color(null, 0, 0, 0));
                }
                
                
            } catch (SQLException e) {
                logger.error("数据库连接失败", e);
                textViewer.getTextWidget().setText("数据库连接失败");
                textViewer.getTextWidget().setForeground(new Color(null, 255, 0, 0));
            }
        }

        
        btn.setVisible(true);
    }
    
    private PropertiesDocument getJdbcConfiguration(final List<String> errors,Boolean load) {
        DatabaseType databaseType=DatabaseType.parse(comboDbType.getText());
        if(databaseType==DatabaseType.None) {
            errors.add("请选择数据库类型··");
            
        }
        if(StringTools.isEmpty(textDbDriver.getText())) {
            errors.add("请输入数据驱动");
        }
        if(StringTools.isEmpty(textDbHost.getText())) {
            errors.add("请输入数据库主机名或IP");
        }
        if(StringTools.isEmpty(textDbPort.getText())) {
            errors.add("请输入数据库端口");
        }
        int port=0;
        try {
            port=Integer.parseInt(textDbPort.getText().trim());            
        }catch (Exception e) {
            errors.add("请输入合法的数据库端口");
        }
        
        if(StringTools.isEmpty(textDbInstance.getText())) {
            errors.add("请输入数据库名称");
        }
        if(StringTools.isEmpty(textDbUser.getText())) {
            errors.add("请输入数据库用户名");
        }
        if(StringTools.isEmpty(textDbPassword.getText())) {
            errors.add("请输入数据库密码");
        }
        if(errors.size()>0) {
            return null;
        }
        DbConnectStringBuilder connectStringBuilder=new DbConnectStringBuilder();
        connectStringBuilder.setDatabaseType(databaseType)
        .setHost(textDbHost.getText().trim())
        .setPort(port)
        .setDbName(textDbInstance.getText().trim())
        .addProperties(textOtherConnectionInfo.getText().trim());
        
        PropertiesDocument propertiesDocument=new PropertiesDocument(true);
        if(load) {
            try {
                propertiesDocument.loadAndMerge(null, true, configFile.getAbsolutePath());
            } catch (IOException e) {
                logger.error("加载代码生成配置信息异常", e);
            }
        }
        propertiesDocument.setProperty(DatabaseConsts.CONFIG_CONNECT_DRIVER_CLASS, textDbDriver.getText().trim());
        propertiesDocument.setProperty(DatabaseConsts.CONFIG_CONNECT_CONNECTION_URL, connectStringBuilder.build());
        propertiesDocument.setProperty(DatabaseConsts.CONFIG_CONNECT_USER_ID, textDbUser.getText().trim());
        propertiesDocument.setProperty(DatabaseConsts.CONFIG_CONNECT_PASSWORD, textDbPassword.getText().trim());
        propertiesDocument.setProperty(DatabaseConsts.CONFIG_CONNECT_SCHEMA, textDbUser.getText().trim());
        propertiesDocument.setProperty(DatabaseConsts.CONFIG_CONNECT_CATALOG, textDbInstance.getText().trim());
        
        return propertiesDocument;
    }

    /**
     * Return the initial size of the dialog.
     */
    @Override
    protected Point getInitialSize() {
        return new Point(600, 550);
    }
}
